package com.tengju.bff.application.wx;

import com.tengju.bff.application.shared.ApplicationException;
import com.tengju.bff.application.shared.ApplicationExceptionCode;
import com.tengju.bff.domain.shared.JsonUtil;
import com.tengju.data.domain.model.wx.*;
import com.tengju.user.domain.model.csm.dealer.CrmDealerInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import static com.tengju.bff.application.shared.ApplicationExceptionCode.WORK_WEIXIN_RECORD_PROCESS_ERROR;
import static com.tengju.data.domain.model.wx.WxRequestRecordType.*;

/**
 * @author: 李大仙
 * @date: 2021/11/25 2:22 下午
 */
@Service
@Slf4j
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class WxUserDepartmentRecordService {

    private final WxRequestRecordRepository wxRequestRecordRepository;
    private final WxUserManageService wxUserManageService;

    int coreSize = Runtime.getRuntime().availableProcessors();
    int maxPoolSize = Math.round(((float) (coreSize * 80)) / 10);
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
            coreSize,
            maxPoolSize,
            1000, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<>(200000));

    public void processCreateDept(Map<Long, CrmDealerInfo> crmDealerInfoMap,
                                  List<WxRequestRecord> wxRequestRecordList) {
        for (WxRequestRecord wxRequestRecord : wxRequestRecordList) {
            WxRequestRecordType wxRequestRecordType = wxRequestRecord.getType();
            WxUserInfo afterWxUserInfo = JsonUtil.toObject(wxRequestRecord.getAfter(), WxUserInfo.class);
            if (afterWxUserInfo == null) {
                throw ApplicationException.error(ApplicationExceptionCode.WORK_WEIXIN_DEALER_INFO_NOT_EXIST, wxRequestRecord.getId());
            }
            WxRequestRecordStatus status = wxRequestRecord.getStatus();
            try {
                if (CREATE_DEPARTMENT == wxRequestRecordType) {
                    long idCodeVal = afterWxUserInfo.getIdCode().getValue();
                    CrmDealerInfo crmDealerInfo = getCrmDealerInfo(crmDealerInfoMap, idCodeVal);
                    String userName = "";
                    if (!StringUtils.isEmpty(crmDealerInfo.getUserName())) {
                        userName = crmDealerInfo.getUserName()
                                .replace("\\", "")
                                .replace(":", "")
                                .replace("?", "")
                                .replace("*", "")
                                .replace("\"", "")
                                .replace("<", "")
                                .replace(">", "")
                                .replace("|", "");
                    }
                    String departmentName = userName + "社群" + crmDealerInfo.getIdCode();
                    wxUserManageService.createDepartment(afterWxUserInfo, departmentName);
                    wxRequestRecord.success();
                    wxRequestRecordRepository.update(wxRequestRecord, status);
                } else if (CREATE_DEALER_DEPARTMENT == wxRequestRecordType) {
                    wxUserManageService.createDealerDepartment(afterWxUserInfo);
                    wxRequestRecord.success();
                    wxRequestRecordRepository.update(wxRequestRecord, status);
                } else if (CREATE_DEPARTMENT_LIMIT_ACCESS_TO_OUTSIDE_DEPARTMENTS_TAG == wxRequestRecordType) {
                    wxUserManageService.createDepartmentLimitAccessToOutsideDepartmentsTag(afterWxUserInfo);
                    wxRequestRecord.success();
                    wxRequestRecordRepository.update(wxRequestRecord, status);
                }
            } catch (Exception e) {
                log.error("processCreateDept error", e);
                wxRequestRecord.fail();
                wxRequestRecordRepository.update(wxRequestRecord, status);
                throw ApplicationException.error(WORK_WEIXIN_RECORD_PROCESS_ERROR, wxRequestRecord.getId());
            }
        }
    }

    public void processDepartmentLeader(List<WxRequestRecord> wxRequestRecordList) {

        for (WxRequestRecord wxRequestRecord : wxRequestRecordList) {
            WxRequestRecordType wxRequestRecordType = wxRequestRecord.getType();
            WxUserInfo afterWxUserInfo = JsonUtil.toObject(wxRequestRecord.getAfter(), WxUserInfo.class);
            if (afterWxUserInfo == null) {
                throw ApplicationException.error(ApplicationExceptionCode.WORK_WEIXIN_DEALER_INFO_NOT_EXIST, wxRequestRecord.getId());
            }
            WxRequestRecordStatus status = wxRequestRecord.getStatus();
            try {
                if (ADD_INTO_CURRENT_DEPARTMENT == wxRequestRecordType) {
                    wxUserManageService.addIntoCurrentDepartment(afterWxUserInfo);
                    wxRequestRecord.success();
                    wxRequestRecordRepository.update(wxRequestRecord, status);
                } else if (MOVE_OUT_CURRENT_DEPARTMENT == wxRequestRecordType) {
                    wxUserManageService.moveOutCurrentDepartment(afterWxUserInfo);
                    wxRequestRecord.success();
                    wxRequestRecordRepository.update(wxRequestRecord, status);
                } else if (ADD_INTO_DEALER_DEPARTMENT == wxRequestRecordType) {
                    wxUserManageService.addIntoDealerDepartment(afterWxUserInfo);
                    wxRequestRecord.success();
                    wxRequestRecordRepository.update(wxRequestRecord, status);
                } else if (MOVE_OUT_DEALER_DEPARTMENT == wxRequestRecordType) {
                    wxUserManageService.moveOutDealerDepartment(afterWxUserInfo);
                    wxRequestRecord.success();
                    wxRequestRecordRepository.update(wxRequestRecord, status);
                }
            } catch (Exception e) {
                log.error("processDepartmentLeader error", e);
                wxRequestRecord.fail();
                wxRequestRecordRepository.update(wxRequestRecord, status);
                throw ApplicationException.error(WORK_WEIXIN_RECORD_PROCESS_ERROR, wxRequestRecord.getId());
            }
        }
    }

    public void processDelete(List<WxRequestRecord> wxRequestRecordList) {
        for (WxRequestRecord wxRequestRecord : wxRequestRecordList) {
            WxRequestRecordType wxRequestRecordType = wxRequestRecord.getType();
            WxUserInfo beforeWxUserInfo = JsonUtil.toObject(wxRequestRecord.getBefore(), WxUserInfo.class);
            if (beforeWxUserInfo == null) {
                throw ApplicationException.error(ApplicationExceptionCode.WORK_WEIXIN_DEALER_INFO_NOT_EXIST, wxRequestRecord.getId());
            }
            WxRequestRecordStatus status = wxRequestRecord.getStatus();
            try {
                if (DELETE_DEPARTMENT == wxRequestRecordType) {
                    wxUserManageService.deleteDepartment(beforeWxUserInfo);
                    wxRequestRecord.success();
                    wxRequestRecordRepository.update(wxRequestRecord, status);
                } else if (DELETE_USER_DEPARTMENT == wxRequestRecordType) {
                    wxUserManageService.deleteUserDepartment(beforeWxUserInfo);
                    wxRequestRecord.success();
                    wxRequestRecordRepository.update(wxRequestRecord, status);
                }
            } catch (Exception e) {
                log.error("processDelete error", e);
                wxRequestRecord.fail();
                wxRequestRecordRepository.update(wxRequestRecord, status);
                throw ApplicationException.error(WORK_WEIXIN_RECORD_PROCESS_ERROR, wxRequestRecord.getId());
            }
        }
    }

    public void processCreateUser(Map<Long, CrmDealerInfo> crmDealerInfoMap,
                            List<WxRequestRecord> wxRequestRecordList) {
        for (WxRequestRecord wxRequestRecord : wxRequestRecordList) {
            WxRequestRecordType wxRequestRecordType = wxRequestRecord.getType();
            WxUserInfo afterWxUserInfo = JsonUtil.toObject(wxRequestRecord.getAfter(), WxUserInfo.class);
            if (afterWxUserInfo == null) {
                throw ApplicationException.error(ApplicationExceptionCode.WORK_WEIXIN_DEALER_INFO_NOT_EXIST, wxRequestRecord.getId());
            }
            WxRequestRecordStatus status = wxRequestRecord.getStatus();

            try {
                if (CREATE_USER_DEPARTMENT == wxRequestRecordType) {
                    long idCodeVal = afterWxUserInfo.getIdCode().getValue();
                    CrmDealerInfo crmDealerInfo = getCrmDealerInfo(crmDealerInfoMap, idCodeVal);
                    wxUserManageService.createUserDepartment(afterWxUserInfo, crmDealerInfo);
                    wxRequestRecord.success();
                    wxRequestRecordRepository.update(wxRequestRecord, status);
                }
            } catch (Exception e) {
                log.error("processCreateUser error", e);
                wxRequestRecord.fail();
                wxRequestRecordRepository.update(wxRequestRecord, status);
            }
        }
    }

    public void processUser(List<WxRequestRecord> wxRequestRecordList) {
        for (WxRequestRecord wxRequestRecord : wxRequestRecordList) {
            WxRequestRecordType wxRequestRecordType = wxRequestRecord.getType();
            WxUserInfo afterWxUserInfo = JsonUtil.toObject(wxRequestRecord.getAfter(), WxUserInfo.class);
            if (afterWxUserInfo == null) {
                throw ApplicationException.error(ApplicationExceptionCode.WORK_WEIXIN_DEALER_INFO_NOT_EXIST, wxRequestRecord.getId());
            }
            WxRequestRecordStatus status = wxRequestRecord.getStatus();

            try {
                if (UPDATE_USER_DEPARTMENT == wxRequestRecordType) {
                    WxUserInfo beforeWxUserInfo = JsonUtil.toObject(wxRequestRecord.getBefore(), WxUserInfo.class);
                    if (beforeWxUserInfo == null) {
                        throw ApplicationException.error(ApplicationExceptionCode.WORK_WEIXIN_DEALER_INFO_NOT_EXIST, wxRequestRecord.getId());
                    }
                    wxUserManageService.updateUserDepartment(beforeWxUserInfo, afterWxUserInfo);
                    wxRequestRecord.success();
                    wxRequestRecordRepository.update(wxRequestRecord, status);
                } else if (UPDATE_DEPARTMENT == wxRequestRecordType) {
                    wxUserManageService.updateDepartment(afterWxUserInfo);
                    wxRequestRecord.success();
                    wxRequestRecordRepository.update(wxRequestRecord, status);
                }
            } catch (Exception e) {
                log.error("processUser error", e);
                wxRequestRecord.fail();
                wxRequestRecordRepository.update(wxRequestRecord, status);
                throw ApplicationException.error(WORK_WEIXIN_RECORD_PROCESS_ERROR, wxRequestRecord.getId());
            }
        }
    }

    public void processHistoryDomination(List<WxRequestRecord> wxRequestRecordList) {
        for (WxRequestRecord wxRequestRecord : wxRequestRecordList) {
            WxRequestRecordType wxRequestRecordType = wxRequestRecord.getType();
            WxUserInfo afterWxUserInfo = JsonUtil.toObject(wxRequestRecord.getAfter(), WxUserInfo.class);
            if (afterWxUserInfo == null) {
                throw ApplicationException.error(ApplicationExceptionCode.WORK_WEIXIN_DEALER_INFO_NOT_EXIST, wxRequestRecord.getId());
            }
            WxUserInfo beforeWxUserInfo = JsonUtil.toObject(wxRequestRecord.getBefore(), WxUserInfo.class);
            if (beforeWxUserInfo == null) {
                throw ApplicationException.error(ApplicationExceptionCode.WORK_WEIXIN_DEALER_INFO_NOT_EXIST, wxRequestRecord.getId());
            }
            WxRequestRecordStatus status = wxRequestRecord.getStatus();
            if (HISTORY_ADD_INTO_CURRENT_DEPARTMENT == wxRequestRecordType) {
                wxUserManageService.historyAddIntoCurrentDepartment(beforeWxUserInfo, afterWxUserInfo);
                wxRequestRecord.success();
                wxRequestRecordRepository.update(wxRequestRecord, status);
            } else if (HISTORY_MOVE_OUT_CURRENT_DEPARTMENT == wxRequestRecordType) {
                wxUserManageService.historyMoveOutCurrentDepartment(beforeWxUserInfo, afterWxUserInfo);
                wxRequestRecord.success();
                wxRequestRecordRepository.update(wxRequestRecord, status);
            }
        }
    }

    private CrmDealerInfo getCrmDealerInfo(Map<Long, CrmDealerInfo> crmDealerInfoMap, Long idCode) {
        CrmDealerInfo crmDealerInfo = crmDealerInfoMap.get(idCode);
        if (crmDealerInfo == null || StringUtils.isEmpty(crmDealerInfo.getMobile())) {
            throw ApplicationException.error(ApplicationExceptionCode.WORK_WEIXIN_DEALER_INFO_NOT_EXIST, idCode);
        }
        return crmDealerInfo;
    }


}
